const WebSocketServer = require('ws').Server
const http = require('http')
const Y = require('yjs')
const fs = require('fs')

// 引入y-leveldb
const { LeveldbPersistence } = require('y-leveldb')

const utils = require('y-websocket/bin/utils')

const port = process.env.PORT || 9879

// 创建存储目录
const storageDir = './yjs-storage-debug'
if (!fs.existsSync(storageDir)) {
    fs.mkdirSync(storageDir, { recursive: true })
    console.log(`📁 创建存储目录: ${storageDir}`)
}

// 设置LevelDB持久化
console.log(`🗄️ 初始化LevelDB持久化 (${new Date().toLocaleTimeString()})`)
const leveldb = new LeveldbPersistence(storageDir)

// 存储上次操作的时间戳
const lastOperationTime = {}

// 调试函数：记录存储状态
async function logStorageStatus() {
    try {
        const docNames = await leveldb.getAllDocNames()
        console.log(`\n📊 ===== LevelDB存储状态 (${new Date().toLocaleTimeString()}) =====`)
        console.log(`📚 文档总数: ${docNames.length}`)

        for (const docName of docNames) {
            const lastTime = lastOperationTime[docName] ?
                new Date(lastOperationTime[docName]).toLocaleTimeString() : '未知'

            // 获取文档元数据
            const lastModified = await leveldb.getMeta(docName, 'lastModified')
            const updateCount = await leveldb.getMeta(docName, 'updateCount') || 0

            console.log(`📄 文档 "${docName}":`)
            console.log(`   - 上次操作: ${lastTime}`)
            console.log(`   - 元数据修改时间: ${lastModified ? new Date(lastModified).toLocaleTimeString() : '未设置'}`)
            console.log(`   - 更新次数: ${updateCount}`)
        }
        console.log(`===========================================\n`)
    } catch (err) {
        console.error(`❌ 获取存储状态时出错:`, err)
    }
}

// 每30秒记录一次存储状态
setInterval(logStorageStatus, 30000)

// 配置持久化
utils.setPersistence({
    bindState: async(docName, ydoc) => {
        console.log(`🔄 绑定文档 "${docName}" (${new Date().toLocaleTimeString()})`)
        try {
            console.log(`📥 尝试从LevelDB加载文档 "${docName}"`)
            const persistedYdoc = await leveldb.getYDoc(docName)
            console.log(`✅ 成功从LevelDB加载文档 "${docName}"`)

            // 记录当前ydoc状态并存储
            console.log(`📤 存储当前文档状态到LevelDB: "${docName}"`)
            const newUpdates = Y.encodeStateAsUpdate(ydoc)
            await leveldb.storeUpdate(docName, newUpdates)

            // 应用已保存的更新
            console.log(`🔄 应用保存的状态到当前文档: "${docName}"`)
            Y.applyUpdate(ydoc, Y.encodeStateAsUpdate(persistedYdoc))

            // 更新元数据
            await leveldb.setMeta(docName, 'lastModified', Date.now())
            const updateCount = (await leveldb.getMeta(docName, 'updateCount') || 0)
            await leveldb.setMeta(docName, 'updateCount', updateCount + 1)

            // 添加文档更新监听器
            ydoc.on('update', async update => {
                lastOperationTime[docName] = Date.now()
                console.log(`📝 文档更新: "${docName}" (${new Date().toLocaleTimeString()})`)
                try {
                    await leveldb.storeUpdate(docName, update)
                    console.log(`💾 已保存更新到LevelDB: "${docName}"`)

                    // 更新元数据
                    await leveldb.setMeta(docName, 'lastModified', Date.now())
                    const count = (await leveldb.getMeta(docName, 'updateCount') || 0)
                    await leveldb.setMeta(docName, 'updateCount', count + 1)
                } catch (err) {
                    console.error(`❌ 保存更新失败 "${docName}":`, err)
                }
            })
        } catch (err) {
            console.error(`❌ 绑定文档状态失败 "${docName}":`, err)
        }
    },
    writeState: async(docName, ydoc) => {
        console.log(`📥 写入状态 (房间可能已关闭): "${docName}" (${new Date().toLocaleTimeString()})`)
        try {
            console.log(`🧹 刷新文档到LevelDB: "${docName}"`)
            await leveldb.flushDocument(docName)
            console.log(`✅ 文档已刷新: "${docName}"`)
        } catch (err) {
            console.error(`❌ 刷新文档失败: "${docName}"`, err)
        }
    }
})

// 创建HTTP服务器，添加调试端点
const server = http.createServer((req, res) => {
    // 设置CORS头
    res.setHeader('Access-Control-Allow-Origin', '*')
    res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS')

    // 调试端点: 列出所有文档
    if (req.url === '/debug/docs') {
        leveldb.getAllDocNames().then(docNames => {
            res.writeHead(200, { 'Content-Type': 'application/json' })
            res.end(JSON.stringify({
                docs: docNames,
                timestamp: new Date().toISOString()
            }))
        }).catch(err => {
            res.writeHead(500, { 'Content-Type': 'application/json' })
            res.end(JSON.stringify({ error: err.message }))
        })
        return
    }

    // 调试端点: 查看存储状态
    if (req.url === '/debug/status') {
        logStorageStatus().then(() => {
            res.writeHead(200, { 'Content-Type': 'text/plain' })
            res.end('存储状态已记录到控制台，请查看服务器日志')
        }).catch(err => {
            res.writeHead(500, { 'Content-Type': 'text/plain' })
            res.end('查看存储状态失败: ' + err.message)
        })
        return
    }

    // 主页
    res.writeHead(200, { 'Content-Type': 'text/html' })
    res.end(`
    <html>
      <head><title>Y.js WebSocket服务器</title></head>
      <body>
        <h1>Y.js WebSocket服务器运行中</h1>
        <p>端口: ${port}</p>
        <p>存储目录: ${storageDir}</p>
        <p>服务器时间: ${new Date().toLocaleString()}</p>
        <h2>调试链接</h2>
        <ul>
          <li><a href="/debug/docs">查看所有文档</a></li>
          <li><a href="/debug/status">查看存储状态</a></li>
        </ul>
      </body>
    </html>
  `)
})

const wss = new WebSocketServer({ server })

wss.on('connection', (ws, req) => {
    console.log(`🔌 新连接 (${new Date().toLocaleTimeString()})`)
    console.log(`📌 URL: ${req.url}`)
    utils.setupWSConnection(ws, req)
})

server.listen(port, () => {
    console.log(`\n🚀 Y.js WebSocket调试服务器启动成功!`)
    console.log(`🌐 服务地址: http://localhost:${port}`)
    console.log(`📂 LevelDB存储目录: ${storageDir}`)
    console.log(`⏰ 启动时间: ${new Date().toLocaleString()}\n`)
})

// 优雅关闭
process.on('SIGINT', async() => {
    console.log(`\n🛑 正在关闭服务器... (${new Date().toLocaleTimeString()})`)
    try {
        // 记录最后的存储状态
        await logStorageStatus()

        // 获取所有文档并刷新
        const docNames = await leveldb.getAllDocNames()
        console.log(`📋 刷新 ${docNames.length} 个文档`)

        for (const docName of docNames) {
            try {
                console.log(`🔄 刷新文档 "${docName}"`)
                await leveldb.flushDocument(docName)
            } catch (err) {
                console.error(`❌ 刷新文档 "${docName}" 失败:`, err)
            }
        }

        // 安全关闭LevelDB
        console.log(`📴 安全关闭LevelDB`)
        await leveldb.destroy()
        console.log(`✅ LevelDB已安全关闭`)
    } catch (err) {
        console.error(`❌ 关闭服务器时出错:`, err)
    }

    console.log(`👋 再见! (${new Date().toLocaleTimeString()})`)
    process.exit(0)
})